home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Floppyshop 2
/
Floppyshop - 2.zip
/
Floppyshop - 2.iso
/
diskmags
/
0022-3.564
/
dmg-3323
/
protocol.gem
/
gfa
/
acc_500.gfa
(
.txt
)
< prev
next >
Wrap
GFA-BASIC Atari
|
1987-04-21
|
16KB
|
522 lines
'
$m 15000
' ACC 500
' Accessoire permettant le pilotage d'autres applications
' Les équivalences issues du fichier ressource
' resource set indicies for ACC_500 */
tube&=0 !form/dialog
cadtube&=0 ! BOX in tree TUBE
tube1&=4 ! BUTTON in tree TUBE
tube2&=5 ! BUTTON in tree TUBE
tube3&=6 ! BUTTON in tree TUBE
tube4&=7 ! BUTTON in tree TUBE
tube5&=8 ! BUTTON in tree TUBE
annutube&=9 ! BUTTON in tree TUBE
nexttube&=10 ! BUTTON in tree TUBE
'
my_menu$=" ACC500/GFA" ! titre du menu de cet ACC
' Les définitions des alertes
alert1$="[1][Accessoire de pilotage (GFA)|Compatible Protocole Tube GEM|Lancement du pilotage ?][Oui|Non]"
alert2$="[1][Choisissez la séquence|qui va être envoyée...][1|2|3]"
alert3$="[1][Notre correspondant|abandonne la communication][OK]"
alert4$="[1][ACC500/GFA|Fichier ressource introuvable|(ACC_500.RSC)][End]"
' Alertes pour le Tube GEM. Attention, il n'y a ici que les textes
' pour les alertes de la série 500 !
alerte_tub1$="[1][Tableau endommagé, |communication par le|Tube GEM impossible.][ OK ]"
alerte_tub2$="[1][Pas d'autres applications|pour l'échange de données][OK]"
alerte_tub2bis$="[1][Pas d'autres applications|pilotables. Désolé...][OK]"
alerte_tub3$="[1][Probléme en $5A0 |Communication par le|Tube GEM impossible][ OK ]"
' Préparons les buffers
DIM new_jar%(31) ! pour Cookie-Jar
DIM tab_tub&(13) ! pour tableau Protocole
DIM messagebuf&(7) ! pour émettre ou recevoir les messages
DIM tab_okapid&(9) ! pour Choice
'
app_id&=APPL_INIT() ! je demande mon identificateur d'application
IF RSRC_LOAD("\ACC_500.RSC")=0
~FORM_ALERT(1,alert4$)
END ! dur avec un ACC mais enfin...
ENDIF
~MENU_REGISTER(app_id&,my_menu$) ! place mon nom dans le menu
' Mise en place du détournement de reset (Cookie-Jar STF)
@put_reset ! deux routines à utiliser à chaque fois,
@init_tube_acc ! et donc à mettre en bibliothéque
'
' Et nous commençons la grande attente !
DO
~EVNT_MESAG(VARPTR(messagebuf&(0))) ! attente des messages...
SELECT messagebuf&(0)
CASE 40 ! ouverture de l'accessoire
@open_acc ! allons le gérer
CASE 300 ! demande si compatible 300
@send_message(messagebuf&(1),301) ! je répond non (301)
CASE 400 ! demande si compatible 400
@send_message(messagebuf&(1),401) ! je répond non (401)
CASE 500 ! demande si compatible 500
@send_message(messagebuf&(1),501) ! je répond non (501)
ENDSELECT
LOOP
'
' Ouverture de l'accessoire. Recherche et vérification du tableau
' des APP_ID à cause d'une destruction toujours possible
> PROCEDURE open_acc
LOCAL action&,adr_action%
action&=FORM_ALERT(1,alert1$)
IF action&=1
@find_apid
IF a0%<>0
@choice_tube(500) !cherche correspondant pour messages 500
IF d0&<>-1
' Nous avons notre correpondant, quelle séquence lui envoyer ?
action&=FORM_ALERT(1,alert2$)
@charge_commande
REPEAT
' Envoyons le message avec les ordres
messagebuf&(0)=506
messagebuf&(1)=app_id&
messagebuf&(2)=0
LPOKE VARPTR(messagebuf&(3)),adr_action%
messagebuf&(5)=0
messagebuf&(6)=0
messagebuf&(7)=0
~APPL_WRITE(d0&,16,VARPTR(messagebuf&(0)))
REPEAT
~EVNT_MESAG(VARPTR(messagebuf&(0)))
UNTIL messagebuf&(0)=505 OR messagebuf&(0)=507 OR messagebuf&(0)=509
UNTIL messagebuf&(0)<>507 ! cas de demande de répétition
' Réagissons suivant la réponse
SELECT messagebuf&(0)
CASE 505 ! Transmission d'ordres terminée, nous prévenons
@send_message(d0&,508)
CASE 509 ! abandon de notre correspondant...
~FORM_ALERT(1,alert3$)
ENDSELECT
ENDIF
ENDIF
ENDIF
RETURN
> PROCEDURE charge_commande
' Cette procédure charge dans une chaine les ordres
' qui seront envoyés à l'application à piloter
SELECT action&
CASE 1
RESTORE seq1
CASE 2
RESTORE seq2
CASE 3
RESTORE seq3
ENDSELECT
' 2000 octets de message, c'est bien suffisant!
adr_action%=GEMDOS(72,L:2000)
t%=adr_action%
DO
READ x&
DPOKE t%,x&
EXIT IF x&=-1
t%=t%+2
SELECT x&
CASE -2 ! le suivant est un paramétre sur 4 octets ?
READ x% ! -2 est l'équivalent de &HFFFE, valeur impossible
LPOKE t%,x% ! à affecter à x&
t%=t%+4
CASE -3 ! paramétre suivant sur 2 octets ?
READ x& ! -3 c'est &HFFFD (même remarque)
DPOKE t%,x&
t%=t%+2
ENDSELECT
LOOP
RETURN
'
' Les procédures suivantes sont simplement à merger.
' Elles sont disponibles dans le dossier Biblio.
> PROCEDURE init_tube_acc
'
' Procédure d'initialisation pour accessoire
' Fichier ACC_INIT.LST
'
cookie4&=0 ! ne pas écraser
init_tub0:
cookie1%=CVL("_TUB") ! cookie recherché
cookie2%=VARPTR(new_jar%(0)) !
cookie3%=VARPTR(tab_tub&(0))
@cookie_jar
'
IF cookie2%<>0
IF cookie3%=VARPTR(tab_tub&(0)) ! si c'est ma liste
tab_tub&(0)=CVI("PR") ! je met son en-tête
tab_tub&(1)=CVI("OT")
tab_tub&(2)=10 ! le nbd d'app_id quelle peut contenir
tab_tub&(3)=app_id& ! mon APP_ID
tab_tub&(4)=-1 ! et la marque de fin
ELSE
' Vérifions le tableau Protocole en place...
IF LPEEK(cookie3%)<>CVL("PROT")
cookie4&=1 ! tableau invalide, nous
GOTO init_tub0 ! allons l'écraser...
ELSE
' Parcourons le tableau en place pour placer
' notre APP_ID et clore par &HFFFF
maxi&=DPEEK(cookie3%+4) ! nbr maxi d'app_id autorisés
cookie3%=cookie3%+6 ! saute l'en-tête
REPEAT
' Nous prévoyons le cas d'ACC lancés par Multidesk
' qui améne à avoir plusieurs fois le même APP_ID:
' Si nous y trouvons déja le notre -> bye bye!!!
EXIT IF DPEEK(cookie3%)=app_id&
IF DPEEK(cookie3%)=&HFFFF ! fin de la liste ?
DPOKE cookie3%,app_id& ! donc met mon APPID
DPOKE cookie3%+2,&HFFFF ! et l'indication de fin
ELSE
cookie3%=cookie3%+2 ! sinon passe à l'app_id
DEC maxi& ! suivant, et le compte
ENDIF
UNTIL DPEEK(cookie3%)=app_id& OR maxi&=0
ENDIF
ENDIF
ENDIF
RETURN
> PROCEDURE soufflage
'
' L'application s'envoi un message et l'attend
' Fichier SOUFLAGE.LST
'
@send_message(app_id&,-1)
REPEAT
~EVNT_MESAG(VARPTR(messagebuf&(0))) ! attente des messages...
UNTIL messagebuf&(0)=-1
RETURN
> PROCEDURE choice_tube(type_cherche&)
LOCAL cmp_apid&,temp%,adr_form%,x_tube%,y_tube%,w_tube%,h_tube%
LOCAL sortie!,dial_tube!,mono_flag&,action&,t&,d5&,d7&
LOCAL cmp_descrip&
'
' Procédure destinée à permettre à l'utilisateur de choisir
' L'application destinatrice. Il est tout a fiat possible
' de présenter celles-ci d'une autre façons.
' Fichier CHOICE.LST
'
a0%=a0%+6
temp%=a0%
sortie!=FALSE
dial_tube!=FALSE ! pour le form_dial
cmp_descrip&=0 ! pour pointer dans tableau de descripteur
d5&=0 ! compteur d'APP_ID (par précaution...)
d7&=tube1&
mono_flag&=0 ! par défaut je suis seul
@soufflage
~RSRC_GADDR(0,tube&,adr_form%)
~FORM_CENTER(adr_form%,x_tube%,y_tube%,w_tube%,h_tube%)
@hide_all ! procédure cachant tous les boutons
REPEAT
' Le GFA permet un teste avec DPEEK et &hFFFF mais
' pas t&=dpeek si le résultat donne &hFFFF !!!!
' Si nous sommes à la fin ou si nous dépassons
IF DPEEK(temp%)=&HFFFF OR d5&>=(DPEEK(a0%-2))
temp%=a0% ! remet temp% au début
d5&=0 ! et init le compteur d'APP_ID
IF d7&<>tube1& ! si nous avons au moins rempli
@gere_formtub ! le premier bouton...
ELSE
' Nous sommes en fin de liste et nous ne nous sommes
' même pas trouvé. Alerte et bye bye...
IF mono_flag&=0
d0&=-1
d1&=-1
sortie!=TRUE
IF jy_suis&=0 ! si théoriquement je suis dans la liste
~FORM_ALERT(1,alert_tub1$)
ENDIF
ENDIF
ENDIF
'
ELSE
t&=DPEEK(temp%) ! préléve l'app_id
INC d5& ! le compte
temp%=temp%+2 ! et avance sur le prochain
' Nous ne sommes pas à la fin de la liste des APP_ID
IF t&=app_id& ! Si l'app_id actuel est le notre
IF mono_flag&=-1
' Nous avons trouvé notre APP_ID mais d'aprés mono_flag
' nous estimons être tout seul dans la liste !
d0&=-1
d1&=-1
sortie!=TRUE
IF type_cherche&=300
~FORM_ALERT(1,alerte_tub2$) ! je suis seul (300)
ELSE
~FORM_ALERT(1,alerte_tub2bis$) ! je suis seul (500)
ENDIF
ELSE
mono_flag&=-1 ! prévenons que nous nous sommes trouvé
ENDIF
ELSE ! l'app_id actuel n'est pas le notre
messagebuf&(0)=type_cherche&
messagebuf&(1)=app_id&
messagebuf&(2)=0
messagebuf&(3)=0
messagebuf&(4)=0
messagebuf&(5)=0
messagebuf&(6)=0
messagebuf&(7)=0
~APPL_WRITE(t&,16,VARPTR(messagebuf&(0)))
' Attendons la réponse
REPEAT
action&=EVNT_MULTI(&X110000,0,0,0,0,0,0,0,0,0,0,0,0,0,VARPTR(messagebuf&(0)),500)
UNTIL (action&=&X10000 AND (messagebuf&(0)=(type_cherche&+1) OR messagebuf&(0)=(type_cherche&+3)) OR action&=&X100000)
'
' si c'est une message 303 (ou 503) du bon correspondant
IF action&=&X10000 AND messagebuf&(0)=type_cherche&+3 AND messagebuf&(1)=t&
num_descrip&=0 ! réception du premier descripteur
act_apid&=messagebuf&(1) ! de l'actuel correspondant
mono_flag&=-2 ! nous ne sommes pas seul
' Nous cherchons l'adresse du bouton à remplir, et nous
' le remplissons avec le descripteur du correspondant
a4%=LPEEK(VARPTR(messagebuf&(3))) ! adresse descripteur
REPEAT
OB_SPEC(adr_form%,d7&)=a4% ! place le texte dans le bouton
OB_FLAGS(adr_form%,d7&)=&H15 !selectable, exit et r_button
tab_okapid&(cmp_descrip&)=act_apid& ! note l'APP_ID
tab_okapid&(cmp_descrip&+1)=num_descrip& ! et le descripteur
cmp_descrip&=cmp_descrip&+2
INC num_descrip&
INC d7& ! on passe au bouton suivant
IF d7&>tube5&
@gere_formtub
EXIT IF sortie!=TRUE
ENDIF
a4%=a4%+34 ! saute 32 oct de texte + flag de fin
UNTIL DPEEK(a4%-2)=&HFF
'
ENDIF
ENDIF
ENDIF
'
UNTIL sortie!=TRUE
RETURN
> PROCEDURE gere_formtub
LOCAL ex%
IF dial_tube!=FALSE
~FORM_DIAL(0,0,0,0,0,x_tube%,y_tube%,w_tube%,h_tube%)
dial_tube!=TRUE
ENDIF
~OBJC_DRAW(adr_form%,0,10,x_tube%,y_tube%,w_tube%,h_tube%)
ex&=FORM_DO(adr_form%,0)
' test du résultat de sortie
OB_STATE(adr_form%,ex&)=BCLR(OB_STATE(adr_form%,ex&),0)
SELECT ex&
CASE annutube&
d0&=-1
d1&=-1
sortie!=TRUE
~FORM_DIAL(3,0,0,0,0,x_tube%,y_tube%,w_tube%,h_tube%)
CASE nexttube&
@hide_all ! on cache tous les boutons (par défaut)
cmp_descrip&=0 ! premier emplacement du tableau ap_id et identf
d7&=tube1& ! premier bouton du formulaire
sortie!=FALSE
DEFAULT
' C'est un des boutons descriptifs
ex&=ex&-tube1& ! pour avoir 0,1,2,3...
ex&=ex&*2 ! car les infos sont par couples
d0&=tab_okapid&(ex&)
d1&=tab_okapid&(ex&+1)
~FORM_DIAL(3,0,0,0,0,x_tube%,y_tube%,w_tube%,h_tube%)
sortie!=TRUE
ENDSELECT
RETURN
> PROCEDURE hide_all
' Par défaut nous cachons tous les boutons
OB_FLAGS(adr_form%,tube1&)=BSET(OB_FLAGS(adr_form%,tube1&),7)
OB_FLAGS(adr_form%,tube2&)=BSET(OB_FLAGS(adr_form%,tube2&),7)
OB_FLAGS(adr_form%,tube3&)=BSET(OB_FLAGS(adr_form%,tube3&),7)
OB_FLAGS(adr_form%,tube4&)=BSET(OB_FLAGS(adr_form%,tube4&),7)
OB_FLAGS(adr_form%,tube5&)=BSET(OB_FLAGS(adr_form%,tube5&),7)
RETURN
> PROCEDURE send_message(dest&,num&)
'
' Pour envoyer un message à une autre application
' Fichier SEND_MES.LST
'
messagebuf&(0)=num& !numéro du message
messagebuf&(1)=app_id& !mon identificateur d'application
messagebuf&(3)=0 !et tout le reste à 0
messagebuf&(4)=0
messagebuf&(5)=0
messagebuf&(6)=0
messagebuf&(7)=0
~APPL_WRITE(dest&,16,VARPTR(messagebuf&(0)))
RETURN
> PROCEDURE find_apid
'
' Recherche de la liste des APP_ID et retour de son
' adresse dans la variable a0%
' C'est une procédure commune aux ACCs et aux PRGs
' Fichier TUBEFIND.LST
'
cookie1%=CVL("_TUB")
cookie2%=0
cookie3%=0
cookie4&=0
@cookie_jar
'
IF cookie2%=0 OR cookie3%=0
~FORM_ALERT(1,alerte_tub3$)
a0%=0
ELSE
IF LPEEK(cookie3%)<>CVL("PROT")
~FORM_ALERT(1,alerte_tub1$)
a0%=0
ELSE
a0%=cookie3%
ENDIF
ENDIF
RETURN
> PROCEDURE cookie_jar
'
' Procédure permettant de lire et/ou d'écrire dans le Cookie-Jar.
' Par simplification, il s'agit de la même routine pour ACC et PRG
' alors qu'il aurait été possible d'en faire des différentes.
' Fichier COOKIJAR.LST
'
LOCAL temp%,x%,cmp%
cookie_jar0:
temp%=LPEEK(&H5A0) !cherche adresse cookie-jar
' S'il n'y a pas de boite, nous plaçons la notre
IF temp%=0
IF cookie2%<>0 ! si nous avons une boite à mettre...
SLPOKE &H5A0,cookie2% ! adresse de celle-ci
IF cookie1%<>0 ! si nous avons un cookie...
LPOKE cookie2%,cookie1%
LPOKE cookie2%+4,cookie3%
LPOKE cookie2%+8,0
LPOKE cookie2%+12,16
ENDIF
ENDIF
ELSE ! Il y a un Cookie-Jar
IF cookie1%<>0 ! si nous devons chercher un gateaux
cmp%=0 ! init. compteur de Cookie
REPEAT
x%=LPEEK(temp%) ! préléve l'identif. d'un cookie
temp%=temp%+8 ! avance sur le suivant
INC cmp% ! et compte ce cookie
UNTIL x%=0 OR x%=cookie1%
temp%=temp%-4 !reculons sur l'info. de ce cookie
' Si nous avons trouvé notre cookie1
IF x%=cookie1%
IF cookie4&=0 ! si nous devons juste noter l'information,
cookie3%=LPEEK(temp%) ! nous la notons et bye bye...
ELSE
LPOKE temp%,cookie3% ! sinon nous la forçons
ENDIF
ELSE
' Nous avons trouvé la fin de la boite, nous mettons
' notre cookie, s'il reste de la place...
IF LPEEK(temps%)=0 ! précaution si nbr de slot nul,
SLPOKE &H5A0,0 ! la boite est mauvaise...
GOTO cookie_jar0
ENDIF
IF cookie3%<>0 ! si nous avons quelque chose à mettre
IF cmp%<LPEEK(temp%) ! s'il reste de la place...
LPOKE (temp%+4),0 ! flag de fin
LPOKE (temp%+8),LPEEK(temp%) ! transfert le nbr d'emplacement
LPOKE (temp%-4),cookie1% ! place l'identif. de notre cookie
LPOKE (temp%),cookie3% ! et sa valeur d'info
ELSE
' Il n'y a pas assez de place: plaçons une plus grosse boite
IF cmp%<16 AND cookie2%<>0 ! si nous pouvons...
temp%=LPEEK(&H5A0) ! adr ancien cookie-jar
SLPOKE &H5A0,cookie2% ! note adr du nouveau
WHILE LPEEK(temp%)<>0
LPOKE cookie2%,LPEEK(temp%)
LPOKE cookie2%+4,LPEEK(temp%+4)
temp%=temp%+8
cookie2%=cookie2%+8
WEND
LPOKE (cookie2%),cookie1%
LPOKE (cookie2%+4),cookie3%
LPOKE (cookie2%+8),0
LPOKE (cookie2%+12),16
ELSE
' Boite pas assez grosse ou pas de boite à mettre ...
cookie3%=0
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
cookie2%=LPEEK(&H5A0)
RETURN
> PROCEDURE put_reset
'
' Procédure pour détourner le reset et y placer une routine
' effaçant le contenu de $5A0 (cas d'un Cookie-Jar de STF)
' Fichier RESET.LST
'
RESTORE asm_data
DO
READ code$
EXIT IF code$="FIN"
code$="&H"+code$
code%=VAL(code$)
asm$=asm$+MKI$(code%)
LOOP
asm%=VARPTR(asm$)
LPOKE asm%+8,LPEEK(&H426) ! prend ancien magique
LPOKE asm%+18,LPEEK(&H42A) ! prend ancienne routine
SLPOKE &H426,&H31415926 ! magique reset
SLPOKE &H42A,asm%
RETURN
asm_data:
DATA 42B9,0000,05A0
DATA 23FC,0000,0000,0000,0426
DATA 23FC,0000,0000,0000,042A
DATA 4ED6,FIN
'
seq1:
DATA 4,2
DATA 6,-3,2,-3,9
DATA 0,-3,75,-3,75,-3,25
DATA 0,-3,120,-3,120,-3,25
DATA 6,-3,2,-3,3
DATA 0,-3,200,-3,200,-3,25
DATA 0,-3,300,-3,300,-3,25
DATA 3,-2,1000
DATA 1,-3,25,-3,25,-3,45,-3,45
DATA 6,-3,1,-3,0
DATA 5,-1
'
seq2:
DATA 4,2
DATA 6,-3,2,-3,15
DATA 1,-3,25,-3,25,-3,75,-3,75
DATA 3,-2,1000
DATA 6,-3,2,-3,16
DATA 1,-3,150,-3,25,-3,200,-3,45
DATA 3,-2,1000
DATA 6,-3,2,-3,17
DATA 1,-3,25,-3,150,-3,45,-3,200
DATA 3,-2,1000
DATA 6,-3,2,-3,18
DATA 1,-3,300,-3,300,-3,350,-3,350
DATA 3,-2,1000
DATA 6,-3,2,-3,19
DATA 1,-3,45,-3,45,-3,65,-3,65
DATA 3,-2,1000
DATA 6,-3,1,-3,0
DATA 5,-1
'
seq3:
DATA 4,2
DATA 6,-3,2,-3,15
DATA 0,-3,100,-3,100,-3,25
DATA 1,-3,25,-3,25,-3,45,-3,45
DATA 0,-3,160,-3,100,-3,25
DATA 1,-3,25,-3,250,-3,45,-3,270
DATA 6,-3,2,-3,2
DATA 0,-3,100,-3,160,-3,25
DATA 1,-3,250,-3,225,-3,230,-3,250
DATA 0,-3,160,-3,160,-3,25
DATA 6,-3,1,-3,0
DATA 5,-1